<?php
namespace api\modules\ua\models;

use Yii;
use yii\db\ActiveRecord;
use yii\db\Exception;
use yii\helpers\ArrayHelper;
use yii\swiftmailer\Mailer;

class Shops extends ActiveRecord
{
    public static function getDb(){return Yii::$app->ua;}
    public static function tableName(){return 'shops';}

    public function fields()
    {
        $fields = parent::fields();
        return $fields;
    }

    // 获取单条记录
    public function getOne($uuid){
        return self::findOne(['uuid'=>$uuid]);
    }

    // 轮询所有设备
    // 登记设备状态：在线/离线
    public function checkOnline(){
        $recordTime = $this->getRecordTime();
        if($recordTime['status']===false) return $recordTime;
        $pingCounts = $this->getPings($recordTime);

        // 获取所有在库的设备uuid
        $status = ["online"=>[],"offline"=>[]];
        foreach ($pingCounts as $ping){
            $uid = $ping['uuid'];
            $count = $ping['count'];
            if($count>10){
                // 执行设备online登记
                $this->registerStatus($uid,'Y', $count, $recordTime);
                array_push($status['online'], $uid);
            }else{
                // 执行设备offline登记
                $this->registerStatus($uid,'N', $count, $recordTime);
                array_push($status['offline'], $uid);
            }
        }

        $status['record'] = $recordTime;
        $status['ping_counts'] = $pingCounts;
        $status['status'] = true;

        // 执行邮件发送
        // 正式环境下，开启邮件发送功能
//        if(count($status['offline'])>0){
//            $this->sendOfflineNotification($recordTime,$status['offline']);
//            $status['email'] = true;
//        }

        return $status;
    }

    // 获取心跳统计
    protected function getPings($pingTime){
        $endTime = $pingTime['date'].' '.$pingTime['time'].":00";
        $startTime = date('Y-m-d H:i:s', strtotime($endTime) - 15 * 60);
        $joinOn = 'p.uuid = s.uuid AND p.ping_time BETWEEN "'.$startTime.'" AND "'.$endTime.'"';
        $query = self::find()
            ->select(['s.uuid', 'COUNT(p.uuid) AS count'])
            ->from('shops s')
            ->leftJoin('shops_ping p', $joinOn)
            ->groupBy('s.uuid')
            ->asArray()
            ->all();
        return $query;
    }


    // 轮询所有设备
    // 登记设备状态：在线/离线
    public function checkOnlineStatus($uuids){
        $onlineUUIDS = json_decode($uuids, true);
        $recordTime = $this->getRecordTime();
        if($recordTime['status']===false) return $recordTime;

        // 获取所有在库的设备uuid
        $res = static::getUuids();
        $list = ArrayHelper::getColumn($res, 'uuid'); // 提取 uuid 字段
        $status = ["online"=>[],"offline"=>[]];
        foreach ($list as $uid){
            if(in_array($uid, $onlineUUIDS)){
                // 执行设备online登记
                $this->registerStatus($uid,'Y', $recordTime);
                array_push($status['online'], $uid);
            }else{
                // 执行设备offline登记
                $this->registerStatus($uid,'N', $recordTime);
                array_push($status['offline'], $uid);
            }
        }

        $status['record'] = $recordTime;
        $status['status'] = true;

        // 执行邮件发送
        // 正式环境下，开启邮件发送功能
//        if(count($status['offline'])>0){
//            $this->sendOfflineNotification($recordTime,$status['offline']);
//            $status['email'] = true;
//        }

        return $status;
    }

    // 获取所有设备uuid，并返回数组
    public static function getUuids()
    {
        return static::find()->select('uuid')->asArray()->all();
    }

    // 获取所有设备uuid，并返回数组
    public static function getShopsByUUIDS($uuids)
    {
        return static::find()
            ->select(['uuid','code','shop','address'])
            ->where(['in','uuid',$uuids])
            ->andWhere(['<>','role','sys'])
            ->asArray()
            ->all();
    }

    // 登记设备：在线/离线
    protected function registerStatus($uuid,$status,$count,$dateTime) {
        // 实现你日志或数据库记录的逻辑
        $online = new Online();
        $online->create($uuid,$status,$count,$dateTime);
    }

    // 发送设备离线通知邮件
    protected function sendOfflineNotification($recordTime,$uuids) {
        $shops = static::getShopsByUUIDS($uuids);

        $currentTime = $recordTime['date'].' '.$recordTime['time'];
        $count = count($uuids);
        $content = "掉线时间\n";
        $content .= "{$currentTime} \n\n";
        $content .= "掉线设备:{$count}台\n";
        foreach ($shops as $item){
            $content .= "{$item['uuid']}\n";
            $content .= "{$item['code']}\n";
            $content .= "{$item['shop']}\n";
            $content .= "{$item['address']}\n\n";
        }

        // 实现你的邮件发送逻辑
        $mailer = Yii::$app->mailer;

        try {
            $mailer->compose()
                ->setFrom('send@pressm.cn') // 发件人
                ->setTo('34n@163.com') // 收件人
                ->setSubject('设备掉线')
                ->setTextBody($content) // 纯文本内容
//            ->setHtmlBody('<b>这是邮件的 HTML 内容</b>') // HTML 内容
                ->send();

//            echo "邮件已成功发送\n";exit;
        } catch (\Exception $e) {
            // 这里可以处理异常，例如记录日志
            echo "发送邮件时发生错误: " . $e->getMessage() . "\n";exit;
        }
    }

    // 获取当前时间对应的记录时间
    protected function getRecordTime()
    {
        // 定义在线时间段
        $onlineTime = Yii::$app->params['ua']['conf']['onlineTime'];

        // 获取当前时间
        date_default_timezone_set('Asia/Shanghai');
        $currentDate = date('Y-m-d');
        $currentTime = date('H:i');

        // 检查当前时间是否在10:00之前或22:00之后
        if ($currentTime < $onlineTime[1] || $currentTime > '22:15') {
            $closestTime = null;
        } else {
            // 初始化上一个时间
            $previousTime = null;

            // 遍历时间列表
            foreach ($onlineTime as $time) {
                // 如果当前时间大于等于列表中的时间
                if ($currentTime > $time) {
                    $previousTime = $time; // 更新上一个时间
                } else {
                    break; // 因为列表是有序的，一旦找到一个晚于当前时间的就可以退出了
                }
            }

            $closestTime = $previousTime;
        }

        $recordTime['date'] = $currentDate;
        if ($closestTime === null) {
            $recordTime['time'] = $currentTime;
            $recordTime['status'] = false;
        } else {
            $recordTime['time'] = $closestTime;
            $recordTime['status'] = true;
        }

        return $recordTime;
    }
}
